#include "protocoleditor.h"
#include"./Utility/Probutility.h"

ProtocolEditor::ProtocolEditor(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::ProtocolEditor)
{
    ui->setupUi(this);
    //this->setStyleSheet("background-color: rgb(500,500,10);");

    auto SetIcon = [&]{
        QIcon icon;
        icon.addPixmap(QPixmap(sQicoPath));
        this->setWindowIcon(icon);
        this->setWindowTitle("协议编辑器");

        ui->findBar_file->setIcon(QIcon(":/Icon/find.png"));
        ui->updateBar_file->setIcon(QIcon(":/Icon/Update.png"));
        ui->commitBar_file->setIcon(QIcon(":/Icon/Commit.png"));

        ui->About_Bar->setIcon(QIcon(":/Icon/About.png"));

        ui->addBar_sys->setIcon(QIcon(":/Icon/Add.png"));
        ui->delBar_sys->setIcon(QIcon(":/Icon/Del.png"));
        ui->editorBar_sys->setIcon(QIcon(":/Icon/Edit.png"));

        ui->addBar_msg->setIcon(QIcon(":/Icon/Add.png"));
        ui->delBar_msg->setIcon(QIcon(":/Icon/Del.png"));
        ui->editorBar_msg->setIcon(QIcon(":/Icon/Edit.png"));

        ui->addBar_data->setIcon(QIcon(":/Icon/Add.png"));
        ui->delBar_data ->setIcon(QIcon(":/Icon/Del.png"));
        ui->editorBar_data->setIcon(QIcon(":/Icon/Edit.png"));

        ui->setBar->setIcon(QIcon(":/Icon/Set.png"));
        ui->about_bar_a->setIcon(QIcon(":/Icon/About.png"));
        ui->exitBar_file_a->setIcon(QIcon(":/Icon/Exit.png"));

        m_MsgEditor = new MsgPanelEditor();

    };

    SetIcon();
    InitToolBarEvent();
    connect(m_MsgEditor,SIGNAL(sendFindOkBtnClick(QString,INT)),this,SLOT(FindSysData(QString,INT)));
    connect(m_MsgEditor,SIGNAL(sendSysEditorBtnClick(INT,QString,EditType)),this,SLOT(SysEditBtnSlot(INT,QString,EditType)));

    connect(m_MsgEditor,SIGNAL(sendSubEditorBtnClick(INT,QString,INT,EditType)),this,SLOT(SubEditBtnSlot(INT,QString,INT,EditType)));
    connect(m_MsgEditor,SIGNAL(sendSubDataEditorBtnClick(INT,QString,QString,EditType)),this,SLOT(SubDataEditBtnSlot(INT,QString,QString,EditType)));
}

ProtocolEditor::~ProtocolEditor()
{
    delete m_MsgEditor;
    delete ui;
}


VOID ProtocolEditor::InIt()
{
    //创建父系统文件夹
    if(!ProbUtility::CreateDirectory(sSysPath))
    {
        qDebug()<<"Create Directiry:"<<sSysPath<<" Is Failed";
        return;
    }
    //创建子系统文件
    if(!ProbUtility::CreateDirectory(sSubPath))
    {
        qDebug()<<"Create Directiry:"<<sSubPath<<" Is Failed";
        return;
    }
    //创建父系统文件
    if(!ProbUtility::CreateFile(sSysPath+sSysFileName))
    {
        qDebug()<<"Create File:"<<sSysFileName<<" Is Failed";
        return;
    }

    const Ui::ProtocolEditor *ui = this->ui;

    auto InitProtocolSysPanel = [&](){
        ui->ProtocolSys->setColumnCount(2);
        ui->ProtocolSys->setHorizontalHeaderLabels(QStringList()<<"<系统ID>"<<"<系统名称>"<<"                     ");
        ui->ProtocolSys->setSelectionBehavior(QAbstractItemView::SelectRows);
        ui->ProtocolSys->setEditTriggers(QAbstractItemView::NoEditTriggers);   //禁止修改
        ui->ProtocolSys->verticalHeader()->setVisible(false);   //隐藏列表头
        //ui->ProtocolSys->setShowGrid(false);
        ui->ProtocolSys->setSelectionMode(QAbstractItemView::SingleSelection);
        ui->ProtocolSys->setColumnWidth(0, 70);
        ui->ProtocolSys->setColumnWidth(1, 180);

        ui->ProtocolSys->setStyleSheet("selection-background-color:gray");  //设置选中行颜色
        connect(ui->ProtocolSys->horizontalHeader(),SIGNAL(sectionClicked(int )),this, SLOT(SortTableByCol(int)));
    };

    auto InitProtocolSubMsgInfoPanel = [&](){
        ui->ProtocolSub->setColumnCount(3);
        ui->ProtocolSub->setHorizontalHeaderLabels(QStringList()<<"<子系统ID>"<<"<子系统名称>"<<"<信息来源>");
        ui->ProtocolSub->setSelectionBehavior(QAbstractItemView::SelectRows);
        ui->ProtocolSub->setEditTriggers(QAbstractItemView::NoEditTriggers);   //禁止修改
        ui->ProtocolSub->verticalHeader()->setVisible(false);   //隐藏列表头
        ui->ProtocolSys->setAlternatingRowColors(true);
        //ui->ProtocolSub->setShowGrid(false);
        ui->ProtocolSub->setSelectionMode(QAbstractItemView::SingleSelection);
        ui->ProtocolSub->setColumnWidth(0, 75);
        ui->ProtocolSub->setColumnWidth(1, 115);
        ui->ProtocolSub->setStyleSheet("selection-background-color:gray");  //设置选中行颜色
    };

    auto InitProtocolSubSystemPanel = [&](){
        ui->Msgexplain->setColumnCount(3);
        ui->Msgexplain->setHorizontalHeaderLabels(QStringList()<<"<数据类型>"<<"<数据描述>"<<"");
        ui->Msgexplain->setSelectionBehavior(QAbstractItemView::SelectRows);
        ui->Msgexplain->setEditTriggers(QAbstractItemView::NoEditTriggers);   //禁止修改
        ui->Msgexplain->verticalHeader()->setVisible(false);   //隐藏列表头
        ui->Msgexplain->setShowGrid(false);
        ui->Msgexplain->setAlternatingRowColors(true);
        ui->Msgexplain->setSelectionMode(QAbstractItemView::SingleSelection);
        ui->Msgexplain->setStyleSheet("selection-background-color:gray");  //设置选中行颜色
    };

    auto InitProtocolSubMsgDataPanel = [&](){
        ui->MsgInfo->setColumnCount(3);
        ui->MsgInfo->setHorizontalHeaderLabels(QStringList()<<"<数据域>"<<"<意义描述>"<<"");
        ui->MsgInfo->setSelectionBehavior(QAbstractItemView::SelectRows);
        ui->MsgInfo->setEditTriggers(QAbstractItemView::NoEditTriggers);   //禁止修改
        ui->MsgInfo->verticalHeader()->setVisible(false);   //隐藏列表头
        ui->MsgInfo->setShowGrid(false);
        ui->MsgInfo->setSelectionMode(QAbstractItemView::SingleSelection);
    };

    QPalette pa = ui->plainTextEdit->palette();
    pa.setColor(QPalette::Base,QColor(162,181,205));
    ui->plainTextEdit->setPalette(pa);

    InitProtocolSysPanel();
    InitProtocolSubMsgInfoPanel();
    InitProtocolSubSystemPanel();
    InitProtocolSubMsgDataPanel();

    LoadSystemConfig(sSysPath,sSysFileName);
    InitSysProtocolPanel();

    //connect(m_MsgEditor,&MsgPanelEditor::onFindOkBtnClick,this,&ProtocolEditor::FindSysData);
}

VOID ProtocolEditor::InitSysProtocolPanel()
{
    if(m_SysProData.isEmpty()) return;
    //初始化父协议面板
    for(auto iter = m_SysProData.begin();iter != m_SysProData.end();++iter)
    {
        AddSystemItem(iter->nId,iter->sName);
    }

    //初始化子协议面板
    auto SysIter= m_SysProData.begin();
    if(SysIter != m_SysProData.end())
    {
        const QVector<SUBPRODEF>* SubData = &SysIter->m_SubPro;
        if(nullptr == SubData) return;
        for(auto iter = SubData->begin();iter != SubData->end();++iter)
        {
            AddSubItem(iter->nSubId,iter->sSubName,iter->nType);
        }

        auto SubDataInfoIter =SubData->begin();
        if(SubDataInfoIter != SubData->end())
        {
            const QVector<SUBPRODATAINFO>* SubDataInfo = &SubDataInfoIter->m_SubProInfo;
            if(nullptr == SubDataInfo) return;
            for(auto iter = SubDataInfo->begin();iter != SubDataInfo->end();++iter)
            {
                AddSubMsgDataItem(iter->nType,iter->sInfo,iter->sRemarks);
            }
        }
    }
    UpdateCurSelect();
    m_SubProtocolType = CLIENT;
}

VOID ProtocolEditor::InitToolBarEvent()
{
    QAction *pExitAction = ui->exitBar_file_a;
    connect(pExitAction,&QAction::triggered,
        []{
            QApplication* app;
            app->exit(0);
        }
    );
    QAction *pFindAction = ui->findBar_file;
    connect(pFindAction,&QAction::triggered,
            [&]{
        this->m_MsgEditor->CreatePanelByType(FINDPANEL,NOTTODO);
    });

    QAction * pSysAddDataAction = ui->addBar_sys;
    connect(pSysAddDataAction,&QAction::triggered,
            [&]{

        this->m_MsgEditor->CreatePanelByType(SYSPANEL,ADD_DATA);
    });

    QAction * pSysEditorDataAction = ui->editorBar_sys;
    connect(pSysEditorDataAction,&QAction::triggered,
            [&]{

        this->m_CurSelItems =ui->ProtocolSys->selectedItems();
        if(m_CurSelItems.isEmpty()) return;
        this->m_MsgEditor->CreatePanelByType(SYSPANEL,EDIT_DATA,&m_CurSelItems);
    });

    QAction * pSubEditorDataAction = ui->editorBar_msg;
    connect(pSubEditorDataAction,&QAction::triggered,
            [&]{
        this->m_CurSelItems = ui->ProtocolSub->selectedItems();
        if(m_CurSelItems.isEmpty()) return;
        this->m_MsgEditor->CreatePanelByType(SUBPANEL,EDIT_DATA,&m_CurSelItems);
    });
    QAction * pSubAddDataAction = ui->addBar_msg;
    connect(pSubAddDataAction,&QAction::triggered,
            [&]{
        this->m_MsgEditor->CreatePanelByType(SUBPANEL,ADD_DATA);
    });

    QAction * pMsgAddDataAction = ui->addBar_data;
    connect(pMsgAddDataAction,&QAction::triggered,
            [&]{
        this->m_MsgEditor->CreatePanelByType(SUBDATAPANEL,ADD_DATA);
    });
    QAction * pMsgEditDataAction = ui->editorBar_data;
    connect(pMsgEditDataAction,&QAction::triggered,
            [&]{
        this->m_CurSelItems = ui->Msgexplain->selectedItems();
        if(m_CurSelItems.isEmpty()) return;
        m_MsgEditor->m_PanelString = ui->plainTextEdit->toPlainText();
        this->m_MsgEditor->CreatePanelByType(SUBDATAPANEL,EDIT_DATA,&m_CurSelItems);
    });

    QAction * pAboutAction = ui->about_bar_a;
    connect(pAboutAction,&QAction::triggered,
            []
    {
            QDialog dia;
            dia.setWindowTitle("说明");
            dia.setWindowIcon(QIcon(":Icon/About.png"));
            QHBoxLayout* btnLayout = new QHBoxLayout(&dia);
            QTextEdit* editor = new QTextEdit(&dia);
            editor->setAlignment(Qt::AlignCenter);
            editor->setText("协议编辑器V1.0版本\n\t\t  By:  TZY\n\t\t  DataTime:\t\t\t  2020-12-17");
            editor->setStyleSheet("background-image:url(:/Icon/aB.jpg);\n"
                                  "background-attachment:fixed;\n"
                                  "background-repeat:none;\n"
                                  "background-position:center");
            editor->setFont(QFont(tr("仿宋"), 13));
            editor->setReadOnly(true);
            btnLayout->addWidget(editor);
            dia.setLayout(btnLayout);
            dia.setFixedSize(300,280);
            dia.exec();
    });


    QAction * pDelSysAction = ui->delBar_sys;
    QAction * pDelSubAction = ui->delBar_msg;
    QAction * pDelMsgAction = ui->delBar_data;

    connect(pDelSysAction,&QAction::triggered,
            [&]
    {
        QList<QTableWidgetItem*> items = ui->ProtocolSys->selectedItems();
        CreateDelMessageBox("选定的系统分类将被删除，删除后数据不可恢复！",SYSPANEL);
    });

    connect(pDelSubAction,&QAction::triggered,
            [&]
    {
        CreateDelMessageBox("选定的协议将被删除，删除后数据不可恢复！",SUBPANEL);
    });
    connect(pDelMsgAction,&QAction::triggered,
            [&]
    {
        CreateDelMessageBox("选定的数据将被删除，删除后数据不可恢复！",SUBDATAPANEL);
    });


    QAction *pToolAction = ui->setBar;
    connect(pToolAction,&QAction::triggered,
            [&]
    {
        QString s = "E:\\Tzy\\qt\\system-protocol\\Protocol\\SysFolder";
        SaveProtocolData(s);
    });

}

void ProtocolEditor::FindSysData(QString sFindData,INT nAllMathc)
{
    if(sFindData.isEmpty())
        return;

    QVector<FINDDATA>& findDataV = m_MsgEditor->m_FindData;
    QVector<FINDDATA::SubData> subVector;

    subVector.clear();
    findDataV.clear();

    INT nProgress = 1;
    INT nFindNum = 0;

    /*
    1.如果只匹配父协议到记录父协议的数据
    2.如果父子协议同时匹配到都记录数据
    3.如果只匹配到子协议就记录父协议的id和子协议的数据
    */
    for(auto iter = m_SysProData.begin();iter != m_SysProData.end();++iter)
    {
        const QString sSysName = iter->sName;
        if(sSysName.isEmpty())
        {
             ++nProgress;
             continue;
        }
        FINDDATA findData;          //系统数据结构
        BOOL bModify = false;
        auto SubDataVec =iter->m_SubPro;
        if(SubDataVec.isEmpty())
        {
           ++nProgress;
           continue;
        }

        //先查子协议是否有匹配的
        for(auto subIter = SubDataVec.begin();subIter != SubDataVec.end();++subIter)
        {
            QString sSubName = subIter->sSubName;
            if(sSubName.isEmpty()) continue;
            FINDDATA::SubData subData;      //子协议数据结构

            if(nAllMathc > 0 )
            {
                if(sSubName.contains(sFindData,Qt::CaseInsensitive))
                {
                    subData.nSubId = subIter->nSubId;
                    subData.sSubData =subIter->sSubName;
                    subData.eType = subIter->nType;
                    findData.m_SubVector.push_back(subData);
                    ++nFindNum;
                }
            }else           //全字符匹配
            {
                for(INT j = 0;j<sFindData.size();++j)
                {
                    QString sSubData =  sFindData.mid(j,2);
                    if(sSubData.size() < 2) break;
                    if(sSubName.contains(sSubData,Qt::CaseInsensitive))
                    {
                        subData.nSubId = subIter->nSubId;
                        subData.sSubData =subIter->sSubName;
                        subData.eType = subIter->nType;
                        findData.m_SubVector.push_back(subData);
                        ++nFindNum;
                        break;
                    }
                }
            }
        }

        //如果子协议没有匹配的，父协议也没有匹配就不记录了。反之记录一下父协议数据就行了
        if(nAllMathc > 0)
        {
            if(sSysName.contains(sFindData,Qt::CaseInsensitive))
            {
                findData.nSysId = iter->nId;
                findData.sMsg =iter->sName;
                ++nFindNum;
                bModify = !bModify;
                findDataV.push_back(findData);
            }
        }else
        {
            for(INT i = 0;i< sFindData.size();++i)
            {
                QString sSysData =  sFindData.mid(i,2);
                if(sSysData.size()<2)break;
                if(sSysName.contains(sSysData,Qt::CaseInsensitive))
                {
                    findData.nSysId = iter->nId;
                    findData.sMsg =iter->sName;
                    ++nFindNum;
                    bModify = !bModify;
                    findDataV.push_back(findData);
                    break;
                }
            }
        }
        //如果子系统不是里面有查到数据且，父系统没有匹配到数据就记录父系统id把子系统加入到数据里
        if(!findData.m_SubVector.isEmpty() && !bModify)
        {
            findData.nSysId = iter->nId;
            ++nFindNum;
            findDataV.push_back(findData);
        }
        m_MsgEditor->UpdateFindProgerssBar(nProgress,m_SysProData.size(),nFindNum);
        ++nProgress;
    }
}

void ProtocolEditor::SysEditBtnSlot(INT nSysId, QString sSysData,EditType eType)
{
    if(eType == NOTTODO) return;

    if(eType == EDIT_DATA)
    {
        auto pItems = ui->ProtocolSys->selectedItems();
        if(!pItems.isEmpty())
        {
            INT nId = ui->ProtocolSys->selectedItems().at(0)->text().toInt();
            PSYSPRODEF data = GetSysDataById(nId);
            PSYSPRODEF newData = GetSysDataById(nSysId);
            if(nullptr != newData && nSysId != nId)
            {
                QMessageBox meg(QMessageBox::Question, "错误","已经存在相同的键值数据", NULL);
                meg.setIcon(QMessageBox::Critical);
                meg.exec();
                return;
            }
            if(nullptr != data)
            {
                UpdateProtocolFile(nId);
                data->nId = nSysId;
                data->sName = sSysData;
                data->m_Status = MoDif;
            }
            //修改
            pItems.at(0)->setText(QString::number(nSysId));
            pItems.at(1)->setText("[ "+sSysData+" ]");
        }
    }else
    {
        PSYSPRODEF newData = GetSysDataById(nSysId);
        if(nullptr != newData)
        {
            QMessageBox meg(QMessageBox::Question, "错误","已经存在相同的键值数据", NULL);
            meg.setIcon(QMessageBox::Critical);
            meg.exec();
            return;
        }
        SYSPRODEF newSysDef;
        newSysDef.nId = nSysId;
        newSysDef.sName = sSysData;
        newSysDef.m_Status = MoDif;
        newSysDef.m_SubPro.clear();
        AddSystemItem(nSysId,sSysData);
    }
    UpdateProtocolFile(0,nSysId,sSysData);
}

void ProtocolEditor::SubEditBtnSlot(INT nSubId, QString nSubData, INT eProType, EditType eType)
{
    qDebug()<<nSubId<<nSubData<<(INT)eProType<<(INT)eType;
    if(eType == NOTTODO) return;

    if(eType == EDIT_DATA)
    {
        auto pItems = ui->ProtocolSub->selectedItems();
        if(!pItems.isEmpty())
        {
            INT nSysId = ui->ProtocolSys->selectedItems().at(0)->text().toInt();
            INT nOldSubId = pItems.at(0)->text().toInt();
            INT nSubType = pItems.at(2)->type();
            PSUBPRODEF data = GetSubSysData(nSysId,nOldSubId,nSubType);
            PSUBPRODEF newData = GetSubSysData(nSysId,nSubId,eProType);
            if(nullptr != newData && nSubId != nOldSubId)
            {
                QMessageBox meg(QMessageBox::Question, "错误","已经存在相同的键值数据", NULL);
                meg.setIcon(QMessageBox::Critical);
                meg.exec();
                return;
            }
            if(nullptr != data)
            {
                data->nSubId = nSubId;
                data->sSubName = nSubData;
                data->nType = (ProtocolType)eProType;
                data->m_Status = MoDif;
            }
            QString sMsgType = "";
            switch ((ProtocolType)eProType)
            {
            case SERVER:
                {
                    const QColor color = QColor(252,222,156);
                    pItems.at(2)->setBackgroundColor(color);
                    pItems.at(1)->setTextColor(QColor(0,0,139));
                    pItems.at(0)->setTextColor(QColor(0,0,139));
                    pItems.at(2)->setTextColor(QColor(0,0,139));
                    sMsgType = "服务器";
                    break;
                }
            case CLIENT:
                sMsgType = "客户端";
                break;
            default:
                break;
            }
            pItems.at(0)->setText(QString::number(nSubId));
            pItems.at(1)->setText(nSubData);
            pItems.at(2)->setText(sMsgType);
            pItems.at(2)->setType(eProType);
        }
    }else
    {
        SUBPRODEF newSubDef;
        newSubDef.nSubId = nSubId;
        newSubDef.sSubName = nSubData;
        newSubDef.m_Status = MoDif;
        newSubDef.nType = (ProtocolType)eProType;
        newSubDef.m_SubProInfo.clear();
        AddSubItem(nSubId,nSubData,(ProtocolType)eProType);
    }
}

void ProtocolEditor::SubDataEditBtnSlot(INT nTypeIdx, QString sData, QString sNote, EditType eType)
{
    if(eType == NOTTODO) return;
    if(eType == EDIT_DATA)
    {
        auto pItems = ui->Msgexplain->selectedItems();
        auto pSubItmes = ui->ProtocolSub->selectedItems();
        if(!pItems.isEmpty() && !pSubItmes.isEmpty())
        {
            INT nSysId =GetSysId();
            INT nSubId = GetSubId();
            INT nMsgId =pItems.at(0)->row();
            INT nSubType = pSubItmes.at(2)->type();
            if(nSysId < 0 || nSubId < 0 || nMsgId < 0) return;

            PSUBPRODATAINFO data = GetSubDataInfoById(nSysId,nSubId,nSubType,nMsgId);
            if(nullptr != data)
            {
                data->m_Status = MoDif;
                data->sInfo = sData;
                data->nType = (PROTOCOLDATATYPE)nTypeIdx;
                data->sRemarks = sNote;
                pItems.at(0)->setText(GetDataInfoType((PROTOCOLDATATYPE)nTypeIdx));
                pItems.at(0)->setType(nTypeIdx);
                pItems.at(1)->setText(sData);
                ui->plainTextEdit->setText(sNote);
            }
        }
    }else
    {
        SUBPRODATAINFO data;
        data.m_Status = MoDif;
        data.nType = (PROTOCOLDATATYPE)nTypeIdx;
        data.sInfo = sData;
        data.sRemarks = sNote;
        AddSubMsgDataItem((PROTOCOLDATATYPE)nTypeIdx,sData,sNote);
    }
}


BOOL ProtocolEditor::LoadSystemConfig(const QString &sSysPath, const QString &sFileName)
{
#if defined(Q_OS_WIN32)
    QFile file(sSysPath+"\\"+sFileName);
#elif defined(Q_OS_MAC )
    QFile file(sSysPath+"/"+sFileName);
#endif
    if(!file.open(QFile::ReadOnly))  return false;

    QDomDocument doc;
    if(!doc.setContent(&file))
    {
        file.close();
        return false;
    }
    file.close();

    QDomElement root = doc.documentElement();
    if(!root.hasChildNodes()) return false;
    QDomNode node = root.firstChild();
    m_SysProData.clear();

    while(!node.isNull())
    {
        if(node.isElement())
        {
            QDomElement ment = node.toElement();
            SYSPRODEF sysData;
            INT nTypeId = ment.attribute("id").toInt();
            sysData.nId = nTypeId;
            sysData.sName = ment.attribute("name");
            m_SysProData.push_back(sysData);
            LoadSubSysttemConfig(sSubPath,nTypeId);
            node = node.nextSibling();
        }
    }
    qSort(m_SysProData.begin(),m_SysProData.end(),[&](const SYSPRODEF& param1,const SYSPRODEF& param2){
        return param1.nId < param2.nId;
    });
    return true;
}

BOOL ProtocolEditor::LoadSubSysttemConfig(const QString &sPath, const INT nTypeId)
{
    QString sFileName;
    const char FileNameBuff[64] = "%d.xml";
    sFileName.sprintf(FileNameBuff,nTypeId);

#if defined(Q_OS_WIN32)
    QFile subFile(sPath+"\\"+sFileName);
#elif defined(Q_OS_MAC )
    QFile subFile(sPath+"/"+sFileName);
#endif

    if(!subFile.open(QIODevice::ReadOnly))
    {
        qWarning()<<"Open File "<<sFileName<<" Is Faild!";
        return false;
    }

    QDomDocument doc;
    INT errorCol;   INT errorLine;QString errorStr;
    if(!doc.setContent(&subFile,true,&errorStr,&errorLine,&errorCol))
    {
        subFile.close();
        qWarning() << errorStr << "line: " << errorLine << "col: " << errorCol;
        QMessageBox::information(NULL, "ErrMsg", errorStr+",FileName:<"+sFileName+"> Line:"+errorLine,
                                 QMessageBox::Close , QMessageBox::Close);
        return false;
    }
    subFile.close();

    QDomElement root = doc.documentElement();
    QDomNode node = root.firstChild();
    PSYSPRODEF SysProData = GetSysDataById(nTypeId);

    while(!node.isNull())
    {
        if(node.isElement())
        {
            QDomElement ment = node.toElement();
            //子协议数据解析
            INT nSubId = ment.attribute("id").toInt();
            SUBPRODEF SubData;
            SubData.nSubId = nSubId;
            SubData.nType = ProtocolType(ment.attribute("type").toInt());
            SubData.sSubName = ment.attribute("name");

            QDomNodeList list=ment.childNodes();
            //遍历子协议下的数据信息
            for(INT i=0;i<list.count();i++) //遍历子元素，count和size都可以用,可用于标签数计数
            {
                QDomNode SubNode=list.at(i);
                if(SubNode.isElement())
                {
                    QDomElement subMent = SubNode.toElement();
                    QDomNode Node=subMent.firstChild();

                    SUBPRODATAINFO SubProData;
                    SubProData.nType =(PROTOCOLDATATYPE)subMent.attribute("type").toInt();      //子协议信息的数据类型(int .....)
                    SubProData.sInfo =subMent.attribute("name");
                    if(Node.isElement())
                    {
                        SubProData.sRemarks =Node.toElement().text();
                    }
                    SubData.m_SubProInfo.push_back(SubProData);
                }
            }
            if(nullptr != SysProData)
            {
                SysProData->m_SubPro.push_back(SubData);
            }
            node = node.nextSibling();
        }
    }
    return true;
}


BOOL ProtocolEditor::AddSystemItem(const UCHAR nTypeId,const QString sName)
{
    INT RowCont;
    RowCont=ui->ProtocolSys->rowCount();
    ui->ProtocolSys->insertRow(RowCont);//

    //插入元素
    QTableWidgetItem *item1 = new QTableWidgetItem(QString::number(nTypeId));
    QTableWidgetItem *item2 = new QTableWidgetItem("[ "+sName+" ]");

    item1->setTextAlignment(Qt::AlignHCenter );

    item1->setTextColor(QColor(0,0,255));
    item2->setTextAlignment(Qt::AlignLeft );
    ui->ProtocolSys->setItem(RowCont,0,item1);
    ui->ProtocolSys->setItem(RowCont,1,item2);
    ui->ProtocolSys->selectRow(0);
    return true;
}

BOOL ProtocolEditor::AddSubItem(const UCHAR nSubId, const QString sName, const ProtocolType nMsgType)
{
    INT RowCont;
    RowCont=ui->ProtocolSub->rowCount();
    ui->ProtocolSub->insertRow(RowCont);

    QString sMsgType = "";
    switch (nMsgType)
    {
    case SERVER:
        sMsgType = "服务器";
        break;
    case CLIENT:
        sMsgType = "客户端";
        break;
    default:
        break;
    }
    //插入元素
    QTableWidgetItem *item1 = new QTableWidgetItem(QString::number(nSubId));
    QTableWidgetItem *item2 = new QTableWidgetItem(sName);
    QTableWidgetItem *item3 = new QTableWidgetItem(sMsgType,nMsgType);
    item1->setTextAlignment(Qt::AlignHCenter );
    item2->setTextAlignment(Qt::AlignLeft );
    item3->setTextAlignment(Qt::AlignLeft );

    if(nMsgType == SERVER)
    {
        const QColor color = QColor(252,222,156);
        item3->setBackgroundColor(color);
        item2->setTextColor(QColor(0,0,139));
        item1->setTextColor(QColor(0,0,139));
        item3->setTextColor(QColor(0,0,139));
    }
    ui->ProtocolSub->setItem(RowCont,0,item1);
    ui->ProtocolSub->setItem(RowCont,1,item2);
    ui->ProtocolSub->setItem(RowCont,2,item3);
    if(RowCont >= 0)
    {
        ui->ProtocolSub->selectRow(0);
    }

    return true;
}

BOOL ProtocolEditor::AddSubMsgDataItem(const PROTOCOLDATATYPE nTypeId, const QString sInfo,const QString  sDescribe)
{
    INT RowCont;
    RowCont=ui->Msgexplain->rowCount();
    ui->Msgexplain->insertRow(RowCont);

    //插入元素
    QString sType = GetDataInfoType(nTypeId);
    QTableWidgetItem *item1 = new QTableWidgetItem(sType,nTypeId);
    QTableWidgetItem *item2 = new QTableWidgetItem(sInfo);
    item1->setTextAlignment(Qt::AlignLeft );
    item1->setTextColor(QColor(30,144,255));
    item2->setTextAlignment(Qt::AlignLeft );

    ui->Msgexplain->setItem(RowCont,0,item1);
    ui->Msgexplain->setItem(RowCont,1,item2);
    ui->plainTextEdit->setText(sDescribe);
    return true;
}

VOID ProtocolEditor::CreateDelMessageBox(const QString sTip, const PanelType eType)
{
    QMessageBox meg(QMessageBox::Question, "提示",sTip, NULL);
    meg.setIcon(QMessageBox::Warning);
    meg.setWindowIcon(QIcon(":/Icon/Del.png"));
    QPushButton *okBtn= meg.addButton(tr("确定"), QMessageBox::AcceptRole);
    meg.addButton(tr("取消"),QMessageBox::RejectRole);
    //QPushButton *cancelBtn = meg.addButton(tr("取消"),QMessageBox::RejectRole);
    meg.exec();
    if ((QPushButton*)meg.clickedButton() == okBtn)//点击确定
    {
        switch (eType) {
        case SYSPANEL:
            DelSystemItem();
            break;
        case SUBPANEL:
            DelSubItem();
            break;
        case SUBDATAPANEL:
            DelSubMsgDataItem();
            break;
        default:
            break;
        }
    }
}

BOOL ProtocolEditor::DelSystemItem()
{
    auto items = ui->ProtocolSys->selectedItems();
    if(items.isEmpty()) return false;
    //删除存储的数据子数据也删除掉

    INT nSysId = items.at(0)->text().toInt();

    for(auto iter = m_SysProData.begin();iter != m_SysProData.end();++iter)
    {
        if(iter->nId == nSysId)
        {
            m_SysProData.erase(iter);
            ui->ProtocolSub->setRowCount(0);
            ui->Msgexplain->setRowCount(0);
            ui->plainTextEdit->clear();
            //把文件删掉
            QString sFilename = sSubPath+"\\"+QString::number(nSysId)+".xml";
            QFile file(sFilename);
            if(file.exists())
            {
                file.remove();
            }
            break;
        }
    }
    ui->ProtocolSys->removeRow(items.at(0)->row());
    UpdateProtocolFile(nSysId);
    return true;
}

BOOL ProtocolEditor::DelSubItem()
{
    auto items = ui->ProtocolSub->selectedItems();
    if(items.isEmpty()) return false;
    ui->ProtocolSys->removeRow(items.at(0)->row());
    //删除存储的数据子数据也删除掉
    PSYSPRODEF sysData = GetSysDataById(GetSysId());
    INT nSubId = items.at(0)->text().toInt();
    if(nullptr != sysData)
    {
        for(auto iter = sysData->m_SubPro.begin();iter !=sysData->m_SubPro.end();++iter )
        {
            qDebug()<<":"<<iter->nSubId <<":"<<nSubId;
            if(iter->nSubId == nSubId)
            {
                sysData->m_SubPro.erase(iter);
                ui->Msgexplain->setRowCount(0);
                ui->plainTextEdit->clear();
                break;
            }
        }
    }
    ui->ProtocolSub->removeRow(items.at(0)->row());
    return true;
}

BOOL ProtocolEditor::DelSubMsgDataItem()
{
    auto subItems = ui->ProtocolSub->selectedItems();
    auto items = ui->Msgexplain->selectedItems();
    if(items.isEmpty() || subItems.isEmpty()) return false;


    INT nSysId = GetSysId();
    INT nSubId = GetSubId();
    INT nSubType =subItems.at(2)->type();

    PSUBPRODEF data = GetSubSysData(nSysId,nSubId,nSubType);
    if(nullptr != data)
    {
        for(auto iter = data->m_SubProInfo.begin();iter != data->m_SubProInfo.end();++iter)
        {
            data->m_SubProInfo.remove(items.at(0)->row());
            ui->plainTextEdit->clear();
            break;
        }
    }
    ui->Msgexplain->removeRow(items.at(0)->row());
    return true;
}

VOID ProtocolEditor::UpdateItemInfo(const INT nTypeId,  INT nSubId)
{
    for(auto iter = m_SysProData.begin();iter != m_SysProData.end();++iter)
    {
        if(iter->nId == nTypeId)
        {
            //初始化子协议面板
            const QVector<SUBPRODEF>* SubData = &iter->m_SubPro;
            if(nullptr == SubData) return;
            for(auto iter = SubData->begin();iter != SubData->end();++iter)
            {
                AddSubItem(iter->nSubId,iter->sSubName,iter->nType);
            }
            //初始化子协议信息内容面板
            if(SubData->isEmpty()) return;
            auto SubDataInfoIter =SubData->at(0);
            const QVector<SUBPRODATAINFO>* SubDataInfo = &SubDataInfoIter.m_SubProInfo;
            if(nullptr == SubDataInfo) return;
            for(auto iter = SubDataInfo->begin();iter != SubDataInfo->end();++iter)
            {
                AddSubMsgDataItem(iter->nType,iter->sInfo,iter->sRemarks);
            }
        }
    }
}

VOID ProtocolEditor::UpdateSubInfo(const INT nTypeId, INT nSubId, ProtocolType type)
{
    PSUBPRODEF DataInfo = GetSubSysData(nTypeId,nSubId,(INT)type);
    if(nullptr == DataInfo) return;

    //初始化子协议信息内容面板
    const QVector<SUBPRODATAINFO>* SubDataInfo = &DataInfo->m_SubProInfo;
    if(nullptr == SubDataInfo) return;
    for(auto iter = SubDataInfo->begin();iter != SubDataInfo->end();++iter)
    {
        AddSubMsgDataItem(iter->nType,iter->sInfo,iter->sRemarks);
    }
}

VOID ProtocolEditor::UpdateSubDataInfo(const INT nTypeId, INT nSubId, ProtocolType type, INT nSubInfoId)
{
    const PSUBPRODATAINFO pSubDataInfo = GetSubDataInfoById(nTypeId,nSubId,type,nSubInfoId);
    if(nullptr == pSubDataInfo) return;
    QString sDescribe = pSubDataInfo->sRemarks;
    ui->plainTextEdit->setText(sDescribe);
}


BOOL ProtocolEditor::SaveProtocolData(const QString& sPath)
{

    if(sPath.isEmpty())
    {
        qDebug()<<"SaveProtocolData file path is nil";
        return false;
    }

    QString sFileName = sPath+"\\Systems.xml";
    qDebug()<<sFileName;
    QFile file(sFileName);
    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug()<<"open file:"<<sFileName<<"faild";
        return false;
    }

    QDomDocument doc;
    if(!doc.setContent(&file))
    {
        qDebug()<<"doc.setContent is faild";
        file.close();
        return false;
    }

    file.close();

    QDomElement root = doc.documentElement();
    if(root.hasChildNodes())    //如果有子节点
    {
        QDomNode node = root.firstChild();


    }else
    {
        return true;
        //创建子节点
        QDomElement subElement = doc.createElement("Communicate");
        //创建属性
        QDomAttr subAttr_ID = doc.createAttribute("id");
        QDomAttr subAttr_Name = doc.createAttribute("name");
        QDomAttr subAttr_Type = doc.createAttribute("type");

        //设置属性的值
        subAttr_ID.setNodeValue("1");
        subAttr_Name.setNodeValue("1");
        subAttr_Type.setNodeValue("1");
        //把属性附加到子节点
        subElement.setAttributeNode(subAttr_ID);
        subElement.setAttributeNode(subAttr_Name);
        subElement.setAttributeNode(subAttr_Type);

        root.appendChild(subElement);    //把数据追加到根节点


 /*
<CType><![CDATA[]]></CType>
  QDomElement e = doc.createElement("CType");
  QDomText text = doc.createTextNode("<![CDATA[]]>");
    e.addendChild(text)
*/
        //保存
        if(!file.open(QIODevice::WriteOnly))
        {
            return false;
        }
        QTextStream docStream(&file);
        doc.save(docStream,4);
        file.close();
    }


    return true;
}

BOOL ProtocolEditor::SaveSubProtocolData(const QString sFileName, const QString sPath)
{
    return true;
}


BOOL ProtocolEditor::UpdateProtocolFile(const INT nType,const INT nId, const QString sData)
{

    QFile file(sSysPath+"\\"+sSysFileName);
    if(!file.exists())return false;

    if(!file.open(QIODevice::ReadWrite))
    {
        qDebug()<<"open file:"<<sSysFileName<<"faild";
        return false;
    }

    QDomDocument doc;
    if(!doc.setContent(&file))
    {
        file.close();
        return false;
    }
    file.close();

    QDomElement root = doc.documentElement();

    auto CreateElementFunc = [&](){
        //创建子节点
        QDomElement subElement = doc.createElement("System");
        //创建属性
        QDomAttr subAttr_ID = doc.createAttribute("id");
        QDomAttr subAttr_Name = doc.createAttribute("name");

        //设置属性的值
        subAttr_ID.setNodeValue(QString::number(nId));
        subAttr_Name.setNodeValue(sData);
        //把属性附加到子节点
        subElement.setAttributeNode(subAttr_ID);
        subElement.setAttributeNode(subAttr_Name);
        root.appendChild(subElement);    //把数据追加到根节点
    };
    qDebug()<<root.childNodes().size();
    if(!root.hasChildNodes())
    {
        CreateElementFunc();
    }
    else
    {
        QDomNodeList list=doc.elementsByTagName("Systems");
        if(!list.isEmpty())
        {
           QDomNodeList childlist =  list.at(0).childNodes();
           auto AddChildNodeFunc = [&](){
               //创建子节点
               QDomElement subElement = doc.createElement("System");
               //创建属性
               QDomAttr subAttr_ID = doc.createAttribute("id");
               QDomAttr subAttr_Name = doc.createAttribute("name");

               //设置属性的值
               subAttr_ID.setNodeValue(QString::number(nId));
               subAttr_Name.setNodeValue(sData);

               //把属性附加到子节点
               subElement.setAttributeNode(subAttr_ID);
               subElement.setAttributeNode(subAttr_Name);
               root.appendChild(subElement);    //把数据追加到根节点
           };
           if(childlist.isEmpty())
           {
                AddChildNodeFunc();
           }else
           {
               BOOL bFind = false;
               for(int i=0;i<childlist.count();i++)
               {
                   QDomElement e=childlist.at(i).toElement();
                   if(e.attribute("id")== QString::number(nId))
                   {
                       QDomNamedNodeMap map = e.attributes();
                       map.namedItem("id").setNodeValue(QString::number(nId));
                       map.namedItem("name").setNodeValue(sData);
                       bFind = !bFind;
                       break;
                   }
               }
               if(!bFind)
               {
                    AddChildNodeFunc();
               }
           }
        }
        else
        {
            CreateElementFunc();
        }
    }

    //保存
    if(!file.open(QIODevice::WriteOnly))
    {
        return false;
    }
    QTextStream docStream(&file);
    doc.save(docStream,4);
    file.close();
    return true;
}

BOOL ProtocolEditor::UpdateProtocolFile(const INT nId)
{
    QFile file(sSysPath+"\\"+sSysFileName);
    if(!file.exists())return false;

    if(!file.open(QIODevice::ReadWrite))
    {
        qDebug()<<"open file:"<<sSysFileName<<"faild";
        return false;
    }

    QDomDocument doc;
    if(!doc.setContent(&file))
    {
        file.close();
        return false;
    }
    file.close();
    qDebug()<<"del1";
    QDomElement root = doc.documentElement();
    if(!root.hasChildNodes()) return false;
    QDomNodeList list=doc.elementsByTagName("Systems");

    if(!list.isEmpty())
    {
       QDomNodeList childlist =  list.at(0).childNodes();
       if(childlist.isEmpty()) return false;
       for(int i=0;i<childlist.count();i++)
       {
           QDomElement e=childlist.at(i).toElement();
           if(e.attribute("id")== QString::number(nId))
           {
                qDebug()<<nId;
               list.at(0).removeChild(childlist.at(i));
               //保存
               if(!file.open(QIODevice::WriteOnly))
               {
                   return false;
               }
               QTextStream docStream(&file);
               doc.save(docStream,4);
               file.close();
               return true;
           }
       }
    }
}

BOOL ProtocolEditor::UpdateSubFile(const INT nId, const)
{

}

PSYSPRODEF ProtocolEditor::GetSysDataById(const INT nSysId)
{

    for(INT i = 0;i< m_SysProData.size();++i)
    {
        if(m_SysProData[i].nId == nSysId)
        {
            return &m_SysProData[i];
        }
    }
    return nullptr;
}

PSUBPRODEF ProtocolEditor::GetSubSysData(const INT nSysId, const INT nSubId, const INT nMsgType)
{
    auto SysData = GetSysDataById(nSysId);
    if(nullptr == SysData) return nullptr;

    QVector<SUBPRODEF>&  SubData  = SysData->m_SubPro;
    for(INT i = 0;i< SubData.size();++i)
    {
        if(SubData[i].nSubId == nSubId && SubData[i].nType == nMsgType)
        {
            return &SubData[i];
        }
    }
    return nullptr;
}

PSUBPRODATAINFO ProtocolEditor::GetSubDataInfoById(const INT nSysId, const INT nSubId, const INT nMsgType,const INT nMsgTypeId)
{
    const PSUBPRODEF SubData = GetSubSysData(nSysId,nSubId,nMsgType);
    if(nullptr == SubData) return nullptr;

    QVector<SUBPRODATAINFO>& SubDataInfo =SubData->m_SubProInfo;

    if(SubDataInfo.size()<=0) return nullptr;
    if(nMsgTypeId >= SubDataInfo.size()) return nullptr;
    return &SubDataInfo[nMsgTypeId];//内存中的数据没有被修改到,需要看下是哪里引用除了问题
}


void ProtocolEditor::SortTableByCol(INT nCol)
{
    // qDebug()<<nCol;
    // ui->ProtocolSys->horizontalHeader()->setSortIndicatorShown(true);
    // ui->ProtocolSys->sortItems(0,Qt::AscendingOrder);
}

void ProtocolEditor::on_ProtocolSys_clicked(const QModelIndex &index)
{
    INT nTypeId = ui->ProtocolSys->item(index.row(),0)->text().toInt();
    UpdateCurSelect(nTypeId);
    ui->ProtocolSub->setRowCount(0);
    ui->Msgexplain->setRowCount(0);
    UpdateItemInfo(nTypeId);
}

void ProtocolEditor::on_ProtocolSys_doubleClicked(const QModelIndex &index)
{
    INT nTypeId = ui->ProtocolSys->item(index.row(),0)->text().toInt();
    UpdateCurSelect(nTypeId);
    this->m_CurSelItems =ui->ProtocolSys->selectedItems();
    if(m_CurSelItems.isEmpty()) return;
    this->m_MsgEditor->CreatePanelByType(SYSPANEL,EDIT_DATA,&m_CurSelItems);
}

void ProtocolEditor::on_ProtocolSub_clicked(const QModelIndex &index)
{
    INT nSysId = GetSysId();

    auto pItems = ui->ProtocolSub->selectedItems();
    if(pItems.isEmpty())return;

    INT nSubId = pItems.at(0)->text().toInt();
    INT nType =  pItems.at(2)->type();
    UpdateCurSelect(nSysId,nSubId);
    m_SubProtocolType = ProtocolType(nType);
    ui->Msgexplain->setRowCount(0);
    UpdateSubInfo(nSysId,nSubId,(ProtocolType)nType);
}

void ProtocolEditor::on_ProtocolSub_doubleClicked(const QModelIndex &index)
{
    INT nSysId = m_CurSelSysIdx;
    INT nSubId = ui->ProtocolSub->item(index.row(),0)->text().toInt();
    UpdateCurSelect(nSysId,nSubId);

    this->m_CurSelItems = ui->ProtocolSub->selectedItems();
    if(m_CurSelItems.isEmpty()) return;
    m_MsgEditor->CreatePanelByType(SUBPANEL,EDIT_DATA,&m_CurSelItems);
}

void ProtocolEditor::on_Msgexplain_doubleClicked(const QModelIndex &index)
{
    INT nSysId = m_CurSelSysIdx;
    INT nSubId = m_CurSelSubIdx;
    INT nSubInfoId = ui->Msgexplain->item(index.row(),0)->text().toInt();
    UpdateCurSelect(nSysId,nSubId,nSubInfoId);
    this->m_CurSelItems = ui->Msgexplain->selectedItems();
    if(m_CurSelItems.isEmpty()) return;
    m_MsgEditor->m_PanelString = ui->plainTextEdit->toPlainText();
    m_MsgEditor->CreatePanelByType(SUBDATAPANEL,EDIT_DATA,&m_CurSelItems);
    //这里崩溃 需要处理

}

void ProtocolEditor::on_Msgexplain_clicked(const QModelIndex &index)
{
    INT nSysId = m_CurSelSysIdx;
    INT nSubId = m_CurSelSubIdx;
    INT nSubInfoId = index.row();
    ProtocolType nSubType = m_SubProtocolType;
    UpdateCurSelect(nSysId,nSubId,nSubInfoId);
    UpdateSubDataInfo(nSysId,nSubId,nSubType,nSubInfoId);
}
